///////////////////////////////////////////////////////////////////////////////
// Project: Hoyo Client Game
//
// hy_random.cpp
// Created: 2013-7-15
// Author: Like Cheng
///////////////////////////////////////////////////////////////////////////////

#include "hy_random.h"

#include "hy_db/hy_db_logic.h"
#include "hy_db/hy_db_const.h"

#include "hy_net/hy_network_message.h"
#include "hy_net/hy_network_default.h"

USING_NS_HY_NETWORK;
hy_random* hy_random_instance = NULL;
///////////////////////////////////////////////////////////////////////////////
//hy_random::hy_random
///////////////////////////////////////////////////////////////////////////////
hy_random::hy_random()
{
}
///////////////////////////////////////////////////////////////////////////////
//hy_random::~hy_random
///////////////////////////////////////////////////////////////////////////////
hy_random::~hy_random()
{

}
///////////////////////////////////////////////////////////////////////////////
//hy_random::instance
///////////////////////////////////////////////////////////////////////////////
hy_random* hy_random::instance()
{
	if( hy_random_instance == NULL )
		hy_random_instance = new hy_random;
	return hy_random_instance;
}
///////////////////////////////////////////////////////////////////////////////
//hy_random::purge_instance
///////////////////////////////////////////////////////////////////////////////
void hy_random::purge_instance()
{
	DEL_POINTER( hy_random_instance );
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::next_int
///////////////////////////////////////////////////////////////////////////////
int hy_random::next_int( int mod )
{
	return next_int() % mod;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::nextInt
///////////////////////////////////////////////////////////////////////////////
int hy_random::next_int( int start, int end )
{
	if( start == end )
	{
		return start;
	}
	else if( start > end )
	{
		int tmp = start;
		start = end;
		end = tmp;
	}

	if( end - start == 1 )
	{
		return pass( 50 ) ? start : end;
	}
	else
	{		
		int r = next_int();
		return start + ( r % ( end + 1 - start ) );
	}
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::next_sign
///////////////////////////////////////////////////////////////////////////////
int hy_random::next_sign()
{
	return ( next_int() & 1 ) ? 1 : -1;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::pass
///////////////////////////////////////////////////////////////////////////////
bool hy_random::pass( int perc )
{
	if( perc <= 0 )
		return false;

	return ( ( next_int() % 100 ) + 1 ) <= perc;
}
///////////////////////////////////////////////////////////////////////////////
// hy_random::pass
///////////////////////////////////////////////////////////////////////////////
bool hy_random::passf( float perc )
{
	if( perc <= 0.0f )return false;
	if( perc >= 1.0f )return true;

	int a = next_int( 0, 10000 );// next_int( 0, 9 ) * 1000 ) + ( next_int( 0, 9 ) * 100 ) + ( next_int( 0, 100 ) );
	int cur_p = perc * 10000.0f;

	return cur_p > a;
}
///////////////////////////////////////////////////////////////////////////////
// hy_random::passf2
///////////////////////////////////////////////////////////////////////////////
bool hy_random::passf2( float perc )
{
	if( perc <= 0.0f )
		return false;
	int a = ( next_int( 0, 99 ) * 100 ) + ( next_int( 0, 99 ) * 10 ) + ( next_int( 0, 99 ) );

	float n_perc = perc * 100.0f;
	return ( ( a % 10000 ) + 1 ) <= n_perc;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::pass_int
///////////////////////////////////////////////////////////////////////////////
int hy_random::pass_int( int perc, int start, int end, int nopassint )
{
	if( pass( perc ) )
	{
		return next_int( start, end );
	}
	return nopassint;
}
///////////////////////////////////////////////////////////////////////////////
// hy_random::pass_float
///////////////////////////////////////////////////////////////////////////////
int hy_random::pass_float( float perc, int start, int end, int nopassint )
{
	float a = perc * 100;

	if( passf( (int)a ) )
	{
		return next_int( start, end );
	}
	return nopassint;
}
///////////////////////////////////////////////////////////////////////////////
// hy_random::random_in_int_vec
///////////////////////////////////////////////////////////////////////////////
int_vec hy_random::random_in_int_vec( int_vec& iv, int num )
{
	int_vec new_iv;
	int_vec::iterator it;

	int_vec tv = iv;
	int t_num = num;
	if( (int)(tv.size()) < num )
	{
		t_num = tv.size();
	}
	for( int i = 0; i < t_num; i++ )
	{
		if( tv.size() - 1 >= 0 )
		{
			int rm = next_int( 0, tv.size()-1 );
			if( rm < (int)(tv.size()) )
			{
				new_iv.push_back( tv.at( rm ) );
				it = tv.begin();
				advance( it, rm );
				if( it != tv.end() )
				{
					tv.erase( it );
				}
			}
		}
	}
	return new_iv;
}
/*
///////////////////////////////////////////////////////////////////////////////
// hy_random::getArrayBySize
///////////////////////////////////////////////////////////////////////////////
PackedIntArray hy_random::getArrayBySize( PackedIntArray& array, int size )
{
	PackedIntArray ret;
	for( int i = 0; i < size; ++i )
	{
		int index = nextInt() % array.size();
		ret.add( array.at( index ) );
		array.remove( index );
	}
	return ret;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::clearProbEntityList
///////////////////////////////////////////////////////////////////////////////
void hy_random::clearProbEntityList()
{
	m_numEntities = 0;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::addProbEntity
///////////////////////////////////////////////////////////////////////////////
void hy_random::addProbEntity( void* entity, int prob )
{
	if( m_numEntities >= MAX_RANDOMED_ENTITIES )
	{
		//GetLog()->write("Error: Random array out of bound!\n");
		return;
	}
	m_entities[m_numEntities].m_entity = entity;
	m_entities[m_numEntities].m_prob = prob;
	m_numEntities++;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::removeProbEntity
///////////////////////////////////////////////////////////////////////////////
void hy_random::removeProbEntity( void* entity )
{
	if( m_numEntities <= 0 )
		return;

	int pos = 0;
	for(; pos < m_numEntities; ++pos)
	{
		if( entity == m_entities[pos].m_entity )
			break;
	}

	if( pos == m_numEntities ) // No found
		return;

	// Move the further slots
	for( int i = pos; i < m_numEntities - 1; ++i )
	{
		m_entities[i].m_entity = m_entities[i+1].m_entity;
		m_entities[i].m_prob = m_entities[i+1].m_prob;
	}
	m_numEntities--;
}

///////////////////////////////////////////////////////////////////////////////
// hy_random::getEntity
///////////////////////////////////////////////////////////////////////////////
void* hy_random::getEntity()
{
	if( m_numEntities <= 0 )
		return NULL;

	int r = nextInt( 100 ) + 1; // [1, 100]
	int count = 0;
	for( int i = 0; i < m_numEntities; ++i )
	{
		count += m_entities[i].m_prob;
		if( r <= count )
			return m_entities[i].m_entity;
	}
	return NULL;
}
*/